Add new domctl hypercall to expose current heap values. This
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 11 Jul 2007 12:03:57 +0000 (13:03 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 11 Jul 2007 12:03:57 +0000 (13:03 +0100)
functionality is needed for probing how much memory is available in a
given node prior to VM creation.

Signed-off-by: Ryan Harper <ryanh@us.ibm.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
tools/libxc/xc_domain.c
tools/libxc/xenctrl.h
xen/common/page_alloc.c
xen/common/sysctl.c
xen/include/public/sysctl.h
xen/include/xen/mm.h

index 11c14247a22effdf5b816d922c56633661cdc583..485b260601d3c915e9f0fb0121ec02380d00d7f8 100644 (file)
@@ -588,6 +588,27 @@ int xc_domain_ioport_permission(int xc_handle,
     return do_domctl(xc_handle, &domctl);
 }
 
+int xc_availheap(int xc_handle,
+                 int min_width,
+                 int max_width,
+                 int node,
+                 uint64_t *bytes)
+{
+    DECLARE_SYSCTL;
+    int rc;
+
+    sysctl.cmd = XEN_SYSCTL_availheap;
+    sysctl.u.availheap.min_bitwidth = min_width;
+    sysctl.u.availheap.max_bitwidth = max_width;
+    sysctl.u.availheap.node = node;
+
+    rc = xc_sysctl(xc_handle, &sysctl);
+
+    *bytes = sysctl.u.availheap.avail_bytes;
+
+    return rc;
+}
+
 int xc_vcpu_setcontext(int xc_handle,
                        uint32_t domid,
                        uint32_t vcpu,
index 6ba6c8b03471652e4a1f47af19234f6e993d5435..93842d4f002bb1a12aec4974e4e091b28d728def 100644 (file)
@@ -616,6 +616,20 @@ int xc_get_pfn_type_batch(int xc_handle, uint32_t dom,
 /* Get current total pages allocated to a domain. */
 long xc_get_tot_pages(int xc_handle, uint32_t domid);
 
+/**
+ * This function retrieves the the number of bytes available
+ * in the heap in a specific range of address-widths and nodes.
+ * 
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm domid the domain to query
+ * @parm min_width the smallest address width to query (0 if don't care)
+ * @parm max_width the largest address width to query (0 if don't care)
+ * @parm node the node to query (-1 for all)
+ * @parm *bytes caller variable to put total bytes counted
+ * @return 0 on success, <0 on failure.
+ */
+int xc_availheap(int xc_handle, int min_width, int max_width, int node,
+                 uint64_t *bytes);
 
 /*
  * Trace Buffer Operations
index e2b64dccab164f897aae66e3f2b45de9af1b6a5c..5012c06e42753ab1c4cff41b79bd0efbae831662 100644 (file)
@@ -936,6 +936,21 @@ void free_domheap_pages(struct page_info *pg, unsigned int order)
         put_domain(d);
 }
 
+unsigned long avail_domheap_pages_region(
+    unsigned int node, unsigned int min_width, unsigned int max_width)
+{
+    int zone_lo, zone_hi;
+
+    zone_lo = min_width ? (min_width - (PAGE_SHIFT + 1)) : (MEMZONE_XEN + 1);
+    zone_lo = max_t(int, MEMZONE_XEN + 1, zone_lo);
+    zone_lo = min_t(int, NR_ZONES - 1, zone_lo);
+
+    zone_hi = max_width ? (max_width - (PAGE_SHIFT + 1)) : (NR_ZONES - 1);
+    zone_hi = max_t(int, MEMZONE_XEN + 1, zone_hi);
+    zone_hi = min_t(int, NR_ZONES - 1, zone_hi);
+
+    return avail_heap_pages(zone_lo, zone_hi, node);
+}
 
 unsigned long avail_domheap_pages(void)
 {
@@ -957,11 +972,6 @@ unsigned long avail_domheap_pages(void)
     return avail_nrm + avail_dma;
 }
 
-unsigned long avail_nodeheap_pages(int node)
-{
-    return avail_heap_pages(0, NR_ZONES - 1, node);
-}
-
 static void pagealloc_keyhandler(unsigned char key)
 {
     unsigned int zone = MEMZONE_XEN;
index efc7c2fd1a4e38f44d09ce8500702283e6591621..98d3777e0a4a27ca1a628db2b92299c22f05f10b 100644 (file)
@@ -21,6 +21,8 @@
 #include <xen/keyhandler.h>
 #include <asm/current.h>
 #include <public/sysctl.h>
+#include <asm/numa.h>
+#include <xen/nodemask.h>
 
 extern long arch_do_sysctl(
     struct xen_sysctl *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl);
@@ -169,6 +171,18 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
     }
     break;
 
+    case XEN_SYSCTL_availheap:
+    { 
+        op->u.availheap.avail_bytes = avail_domheap_pages_region(
+            op->u.availheap.node,
+            op->u.availheap.min_bitwidth,
+            op->u.availheap.max_bitwidth);
+        op->u.availheap.avail_bytes <<= PAGE_SHIFT;
+
+        ret = copy_to_guest(u_sysctl, op, 1) ? -EFAULT : 0;
+    }
+    break;
+
     default:
         ret = arch_do_sysctl(op, u_sysctl);
         break;
index 06eb0e78c5d3a5a6365696aaffab2feb5bea5da7..1088a275e083fb4c51405f4bcb22ab6786e8f6b2 100644 (file)
@@ -185,6 +185,18 @@ struct xen_sysctl_getcpuinfo {
 typedef struct xen_sysctl_getcpuinfo xen_sysctl_getcpuinfo_t;
 DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getcpuinfo_t); 
 
+#define XEN_SYSCTL_availheap         9
+struct xen_sysctl_availheap {
+    /* IN variables. */
+    uint32_t min_bitwidth;  /* Smallest address width (zero if don't care). */
+    uint32_t max_bitwidth;  /* Largest address width (zero if don't care). */
+    int32_t  node;          /* NUMA node of interest (-1 for all nodes). */
+    /* OUT variables. */
+    uint64_t avail_bytes;   /* Bytes available in the specified region. */
+};
+typedef struct xen_sysctl_availheap xen_sysctl_availheap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_availheap_t);
 struct xen_sysctl {
     uint32_t cmd;
     uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
@@ -197,6 +209,7 @@ struct xen_sysctl {
         struct xen_sysctl_getdomaininfolist getdomaininfolist;
         struct xen_sysctl_debug_keys        debug_keys;
         struct xen_sysctl_getcpuinfo        getcpuinfo;
+        struct xen_sysctl_availheap         availheap;
         uint8_t                             pad[128];
     } u;
 };
index a94d4efdb0f2a36ed247eb622af17fafed10b60f..a5183fd125199ab67f2816a3cacf011c97238020 100644 (file)
@@ -61,6 +61,8 @@ struct page_info *__alloc_domheap_pages(
     struct domain *d, unsigned int cpu, unsigned int order, 
     unsigned int memflags);
 void free_domheap_pages(struct page_info *pg, unsigned int order);
+unsigned long avail_domheap_pages_region(
+    unsigned int node, unsigned int min_width, unsigned int max_width);
 unsigned long avail_domheap_pages(void);
 #define alloc_domheap_page(d) (alloc_domheap_pages(d,0,0))
 #define free_domheap_page(p)  (free_domheap_pages(p,0))